/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.tnmk.worktime.gui.utils;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultRowSorter;
import javax.swing.InputMap;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import org.tnmk.worktime.gui.tbl.DateCellRenderer;
import org.tnmk.worktime.gui.tbl.DecorateDefaultTableCellRenderer;
import org.tnmk.worktime.gui.tbl.NumberCellRenderer;
import org.tnmk.worktime.gui.tbl.TimeCellRenderer;

/**
 *
 * @author Administrator
 */
public class JTableUtils {

  public static final KeyStroke[] NEXT_FOCUS_KEYS = new KeyStroke[]{KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)};

  public static void addCellEditorListenerToAllColumns(JTable jtbl, CellEditorListener listener) {
    DefaultTableModel model = (DefaultTableModel) jtbl.getModel();
    int colCount = model.getColumnCount();
    Set<Class> colClasses = new HashSet<>();
    for (int i = 0; i < colCount; i++) {
      Class colClass = model.getColumnClass(i);
      colClasses.add(colClass);
    }
    for (Class colClass : colClasses) {
      jtbl.getDefaultEditor(colClass).addCellEditorListener(listener);
    }
  }

  public static void setCell(JTable jtbl, int col, TableCellRenderer cellRenderer, TableCellEditor cellEditor) {
    TableColumnModel colModel = jtbl.getColumnModel();
    TableColumn editCol = colModel.getColumn(col);
    if (cellRenderer != null) {
      editCol.setCellRenderer(cellRenderer);
    }
    if (cellEditor != null) {
      editCol.setCellEditor(cellEditor);
    }
  }

  public static void setHeader(JTable jtbl, int col, Object headerValue) {
    jtbl.getTableHeader().getColumnModel().getColumn(col).setHeaderValue(headerValue);
    jtbl.getTableHeader().repaint();
  }

  /**
   * @param jtbl
   * @param row this is the row index of JTable, not the row index of JTable Model
   * @param keyCol the column contains the value which will distinct rows
   * @return the index of corresponding row in Model
   */
  public static int findModelRow(JTable jtbl, int row, int keyCol) {
    Object keyVal = jtbl.getValueAt(row, keyCol);
    DefaultTableModel model = (DefaultTableModel) jtbl.getModel();
    int modelRowCount = model.getRowCount();
    for (int i = 0; i < modelRowCount; i++) {
      Object modelKeyVal = model.getValueAt(i, keyCol);
      if (keyVal.equals(modelKeyVal)) {
        return i;
      }
    }
    return -1;
  }

  public static void removeRow(JTable jtbl, int row, int keyCol) {
    int rowModelIndex = findModelRow(jtbl, row, keyCol);
    if (rowModelIndex < 0) {
      return;
    } else {
      DefaultTableModel model = (DefaultTableModel) jtbl.getModel();
      model.removeRow(rowModelIndex);
    }
  }

  public static void setDateTimeFormat(JTable jtbl, int col) {
    TableColumnModel colModel = jtbl.getColumnModel();
    TimeCellRenderer timeRenderer = new TimeCellRenderer();
    colModel.getColumn(col).setCellRenderer(timeRenderer);
  }

  public static void setNumberFormat(JTable jtbl, int col) {
    TableColumnModel colModel = jtbl.getColumnModel();
    NumberCellRenderer renderer = new NumberCellRenderer();
    colModel.getColumn(col).setCellRenderer(renderer);
  }

  public static void setWidth(JTable jtbl, int col, int width) {
    jtbl.getColumnModel().getColumn(col).setMaxWidth(width);
    jtbl.getColumnModel().getColumn(col).setPreferredWidth(width);
  }

  public static void setDateFormat(JTable jtbl, int col) {
    TableColumnModel colModel = jtbl.getColumnModel();
    DateCellRenderer timeRenderer = new DateCellRenderer();
    colModel.getColumn(col).setCellRenderer(timeRenderer);
  }

  public static void addRenderer(JTable jtbl, int col, TableCellRenderer renderer) {
    TableColumnModel colModel = jtbl.getColumnModel();
    TableColumn tableColumn = colModel.getColumn(col);
    if (renderer instanceof DecorateDefaultTableCellRenderer) {
      DecorateDefaultTableCellRenderer decorateCellRenderer = (DecorateDefaultTableCellRenderer) renderer;
      TableCellRenderer previousRenderer = tableColumn.getCellRenderer();
      if (previousRenderer instanceof DefaultTableCellRenderer) {
        decorateCellRenderer.setPreviousCellRenderer((DefaultTableCellRenderer) previousRenderer);
      }
    }
    tableColumn.setCellRenderer(renderer);
  }

  public static void disableFocusOnColumn(JTable jtbl, final int disableFocusColumn) {
    InputMap im = jtbl.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    for (KeyStroke key : NEXT_FOCUS_KEYS) {
      final Action oldTabAction = jtbl.getActionMap().get(im.get(key));
      Action tabAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
          oldTabAction.actionPerformed(e);
          JTable table = (JTable) e.getSource();
          int col = table.getSelectedColumn();
          while (col == disableFocusColumn) {
            oldTabAction.actionPerformed(e);
            col = table.getSelectedColumn();
          }
        }
      };
      jtbl.getActionMap().put(im.get(key), tabAction);
    }
  }

  public static void sortColumn(JTable jtbl, int col, boolean sortable) {
    DefaultRowSorter sorter = (DefaultRowSorter) jtbl.getRowSorter();
    sorter.setSortable(col, sortable);
  }

  public static void sortColumn(JTable jtbl, int col, SortOrder sortOrder) {
    List<RowSorter.SortKey> sortKeys = new ArrayList<>();
    sortKeys.add(new RowSorter.SortKey(col, sortOrder));
    jtbl.getRowSorter().setSortKeys(sortKeys);
  }

  public static void setNextFocusByColumn(JTable jtbl) {
    InputMap inputMap = jtbl.getInputMap();
    for (KeyStroke key : NEXT_FOCUS_KEYS) {
      inputMap.put(key, "selectNextColumnCell");
    }
  }
}
